/*建造者模式*/

#include <iostream>
#include <string>
#include <memory>
using namespace std;

//抽象电脑类 - 有华硕电脑 华为电脑 苹果电脑等等
class Computer
{
public:
    void setBoard(const string& board) { _board = board; }
    void setDisplay(const string& display) { _display = display; }
    virtual void setOS() = 0; //操作系统根据不同的电脑 自己决定

    Computer() {}
    void PrintConfig()
    {
        cout<<"电脑配置:"<<endl;
        cout<<"\t"<<"主板:"<<_board<<endl;
        cout<<"\t"<<"显示器:"<<_display<<endl;
        cout<<"\t"<<"操作系统:"<<_os<<endl;
    }
    
protected:
    string _board; //电脑主板
    string _display; //电脑显示器
    string _os; //电脑操作系统
};

//具体电脑类
class MacComputer : public Computer
{
public:
    MacComputer() {}
    void setOS() override { _os = "MacOS 17.0(Unix)"; }
};

//建造者提供建造不同电脑的抽象方法 - 根据不同的电脑 具体化不同电脑对应建造的方法实现
class Builder
{
public:
    virtual void buildBoard(const string& build) = 0;
    virtual void builddDisplay(const string& display) = 0;
    virtual void buildOS() = 0;
    virtual shared_ptr<Computer> build() = 0; //获取该电脑组装后的对象
};

//对应具体电脑类的建造方法(注意:建造者并不知道安装顺序 只知道如何制作 例如没有主板是不能安装操作系统的 安装的顺序需要靠指挥者)
class MacBuilder : public Builder
{
public:
    //建造者携带电脑框架(配件) 等待指挥者指挥建造
    MacBuilder():_macpc(new MacComputer) {}
    //安装主板
    void buildBoard(const string& build) override 
    {
        _macpc->setBoard(build);
    }
    //安装显示器
    void builddDisplay(const string& display) override 
    {
        _macpc->setDisplay(display);
    }
    //安装操作系统
    void buildOS() override 
    {
        _macpc->setOS();
    }
    //获取该电脑组装后的对象
    shared_ptr<Computer> build() override 
    {
        return _macpc;
    }

private:
    //实例化电脑类 指定要建造的电脑
    shared_ptr<Computer> _macpc;
};

//指挥者类-控制建造者类以合理的顺序制造电脑
class Director
{
public:
    //初始化建造者 使用用户创建的指定 建造者地址
    Director(Builder* builder):_build(builder) {}

    //指挥者指挥建造者按照要求创造电脑
    void construct(const string& build,const string& display)
    {
        _build->buildBoard(build);
        _build->builddDisplay(display);
        _build->buildOS();
    }
    
private:
    shared_ptr<Builder> _build; //指挥者改造一个建造者 来建造电脑
};

int main()
{
    //先创建一个对应电脑的建造者
    Builder* MacBuild = new MacBuilder;

    //创造指挥者 管理建造者去建造电脑
    unique_ptr<Director> director(new Director(MacBuild));

    //建造电脑
    director->construct("华为主板","华星光电屏幕");

    //用户获取电脑
    shared_ptr<Computer> mac(MacBuild->build());

    //获取电脑配置
    mac->PrintConfig();
    
    return 0;
}

//电脑框架
//建造者
//指挥者

//建造者携带电脑框架和配件等待指挥者指挥建造